package com.ruoyi.common.utils;

import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 线程相关工具类.
 *
 * @author ruoyi
 */
public class Threads {
    private static final Logger logger = LoggerFactory.getLogger(Threads.class);

    /**
     * 使当前线程休眠指定的毫秒数。
     *
     * @param milliseconds 休眠时间（单位：毫秒）
     */
    public static void sleep(long milliseconds) {
        try {
            Thread.sleep(milliseconds);
        } catch (InterruptedException e) {
            return;
        }
    }

    /**
     * 安全地关闭线程池，并等待其终止。
     * <p>
     * 首先调用 {@code shutdown()} 方法停止接收新任务并尝试完成已有任务；
     * 若在120秒内未完全终止，则调用 {@code shutdownNow()} 强制取消队列中的任务并中断所有阻塞线程；
     * 若再次超时仍未终止，则记录日志提示线程池未能正常关闭。
     * 同时处理了在关闭过程中线程被中断的情况。
     * </p>
     *
     * @param pool 要关闭的线程池对象，可以为null
     */
    public static void shutdownAndAwaitTermination(ExecutorService pool) {
        if (pool != null && !pool.isShutdown()) {
            pool.shutdown();
            try {
                // 等待最多120秒让已提交的任务执行完毕
                if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
                    // 超时则强制关闭
                    pool.shutdownNow();
                    // 再次等待最多120秒确认是否成功关闭
                    if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
                        logger.info("Pool did not terminate");
                    }
                }
            } catch (InterruptedException ie) {
                // 当前线程被中断时也强制关闭线程池
                pool.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }

    /**
     * 捕获并打印线程执行过程中的异常信息。
     * <p>
     * 如果传入的Runnable是一个Future实例且没有显式抛出异常，
     * 则通过{@code get()}方法获取潜在的执行异常并进行记录。
     * 最终将异常信息输出到日志系统中。
     * </p>
     *
     * @param r 正在执行的任务对象
     * @param t 抛出的异常对象，可能为null
     */
    public static void printException(Runnable r, Throwable t) {
        if (t == null && r instanceof Future<?>) {
            try {
                Future<?> future = (Future<?>) r;
                if (future.isDone()) {
                    future.get();
                }
            } catch (CancellationException ce) {
                t = ce;
            } catch (ExecutionException ee) {
                t = ee.getCause();
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
            }
        }
        if (t != null) {
            logger.error(t.getMessage(), t);
        }
    }
}
